package com.ete.lib.upload.logZip

import android.Manifest
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.PermissionUtils
import com.blankj.utilcode.util.ThreadUtils
import com.ete.lib.upload.R
import com.ete.lib.upload.UploadManager
import com.ete.lib.upload.UploadConstant
import net.lingala.zip4j.exception.ZipException
import net.lingala.zip4j.model.ZipParameters
import net.lingala.zip4j.util.Zip4jConstants
import java.io.File

/**
 * Author:LiXian
 * <p>
 * Desc:压缩文件
 * Version:1.0
 * date 2024/1/8 13:42
 */
object ZipFileUtil {

    private var mTask: ThreadUtils.SimpleTask<String>? = null

    /**
     * (有密码)压缩文件夹或者文件
     * @param fromZipPath 待压缩的文件夹或文件全路径
     * @param toZipPath 压缩到的文件路径...zip
     * @param zipPassword 压缩密码（若为null，则无密码）
     */
    @JvmStatic
    @JvmOverloads
    fun zipDirFile(fromZipPath: String, toZipPath: String, callback: IZipCallback, zipPassword: String? = null) {
        if (!PermissionUtils.isGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            LogUtils.d(UploadManager.TAG, "无读写权限")
            callback.onError(UploadConstant.ERROR_ONT_PERMISSION,
                    UploadLogUtil.getString(R.string.upload_not_permission))
            return
        }
        if (!FileUtils.isFileExists(fromZipPath)) {
            LogUtils.d(UploadManager.TAG, "压缩文件源不存在")
            callback.onError(UploadConstant.ERROR_ONT_SCR_FILE,
                    UploadLogUtil.getString(R.string.upload_zip_file_not_exists))
            return
        }
        if (FileUtils.isFileExists(toZipPath)) {
            LogUtils.d(UploadManager.TAG, "压缩文件已存在")
            callback.onSuccess(fromZipPath, toZipPath)
            return
        }
        cancelTask()
        callback.onStart()
        mTask = object : ThreadUtils.SimpleTask<String>() {
            override fun doInBackground(): String {
                startZipFile(fromZipPath, toZipPath, callback, zipPassword)
                return ""
            }

            override fun onSuccess(result: String?) {
                LogUtils.d(UploadManager.TAG, "解压任务成功")
                cancelTask()
            }

            override fun onFail(t: Throwable?) {
                super.onFail(t)
                LogUtils.d(UploadManager.TAG, "解压任务失败error:[${t?.message}]")
                cancelTask()
            }

            override fun onDone() {
                super.onDone()
                cancelTask()
            }
        }
        ThreadUtils.executeByIo(mTask)
    }

    @JvmStatic
    private fun startZipFile(fromZipPath: String, toZipPath: String, callback: IZipCallback, zipPassword: String? = null) {
        val fromFile = File(fromZipPath)
        val toFile = File(toZipPath)
        val mZipProgress = ZipProgress(fromZipPath, toZipPath, callback)
        try {
            val zipFile = ZipFile(toFile, mZipProgress)
            //设置编码格式（支持中文）
            zipFile.setFileNameCharset("GBK")
            val zipParameters = ZipParameters()
            zipParameters.compressionMethod = Zip4jConstants.COMP_DEFLATE
            zipParameters.compressionLevel = Zip4jConstants.DEFLATE_LEVEL_NORMAL
            //是否要加密(加密会影响压缩速度)
            if (!zipPassword.isNullOrEmpty()) {
                zipParameters.isEncryptFiles = true
                //加密方式
                zipParameters.encryptionMethod = Zip4jConstants.ENC_METHOD_STANDARD
                zipParameters.setPassword(zipPassword)
            }
            //压缩文件夹
            if (fromFile.isDirectory) {
                zipFile.addFolder(fromFile, zipParameters);
            }
            //压缩文件
            else {
                zipFile.addFile(fromFile, zipParameters);
            }
        } catch (ex: Exception) {
            ex.printStackTrace()
            LogUtils.d(UploadManager.TAG, "压缩文件夹错误error:[${ex.message}]")
            FileUtils.delete(toZipPath)
        }
    }

    /**
     * (有密码)解缩文件夹或者文件
     * @param fromZipPath 压缩到的文件路径....zip
     * @param toZipPath 解压的文件夹路径
     * @param zipPassword 压缩密码（若为null，则无密码）
     */
    @JvmStatic
    @JvmOverloads
    fun unZipDirFile(fromZipPath: String, toZipPath: String, callback: IZipCallback, zipPassword: String? = null) {
        val fromFile = File(fromZipPath)
        val toFile = File(toZipPath)
        try {
            val mZipProgress = ZipProgress(fromZipPath, toZipPath, callback)
            val zipFile = ZipFile(fromFile, mZipProgress)
            //设置编码格式（支持中文）
            zipFile.setFileNameCharset("GBK")
            //检查输入的zip文件是否是有效的zip文件
            if (!zipFile.isValidZipFile) {
                throw ZipException("压缩文件不合法,可能被损坏")
            }
            //创建解压至的文件夹
            if (toFile.isDirectory && !toFile.exists()) {
                toFile.mkdir()
            }
            //压缩包是否加密
            if (zipFile.isEncrypted) {
                if (zipPassword.isNullOrEmpty()) {
                    throw ZipException("压缩文件已加密，请输入密码")
                }
                zipFile.setPassword(zipPassword)
            }
            //解压至文件夹
            zipFile.extractAll(toZipPath);
        } catch (ex: ZipException) {
            LogUtils.e(UploadManager.TAG, "解压异常error:[${ex.message}]")
        }
    }

    @JvmStatic
    fun cancelTask() {
        mTask?.cancel()
        mTask = null
    }
}